package org.example.service.diary.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.mapper.DiaryInfoMapper;
import org.example.model.common.AppHttpCodeEnum;
import org.example.model.common.PageResponseDto;
import org.example.model.common.ResponseResult;
import org.example.model.diary.dtos.DiaryContentByMonthDto;
import org.example.model.diary.dtos.DiaryCountGroupByDayDto;
import org.example.model.diary.dtos.DiaryInfoDto;
import org.example.model.diary.entities.DiaryInfo;
import org.example.model.diary.enums.DiaryType;
import org.example.model.diary.vos.AddDiaryInfoVo;
import org.example.model.diary.vos.SearchDiaryInfoVo;
import org.example.model.user.dtos.UserIdentityDto;
import org.example.service.diary.DiaryInfoService;
import org.example.service.project.ProjectInfoService;
import org.example.utils.UserIdThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 日报信息服务层实现
 */
@Service
@Transactional
@Slf4j
public class DiaryInfoServiceImpl extends ServiceImpl<DiaryInfoMapper, DiaryInfo> implements DiaryInfoService {

    // 日报信息数据映射层接口
    @Autowired
    private DiaryInfoMapper diaryInfoMapper;

    /**
     * 添加一则日报信息记录
     * @param belongUserId 日报所属人id
     */
    @Override
    public ResponseResult<Boolean> InsertDiaryInfo(Integer belongUserId) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (belongUserId == null || belongUserId <= 0) {
            // 缺少参数 日报所属人id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        // 生成一条日报记录默认值
        DiaryInfo diaryInfo = new DiaryInfo();
        diaryInfo.setDailyNewsName("学习日报");
        diaryInfo.setDailyNewsType(DiaryType.Learn.ordinal());
        diaryInfo.setProjectId(0);
        diaryInfo.setWorkHours(0);
        diaryInfo.setWorkDetail("");
        diaryInfo.setBelongUserId(belongUserId);
        this.HandleModifyDiaryInfo(diaryInfo);
        // 插入日报信息表
        Boolean flag = diaryInfoMapper.insert(diaryInfo) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 添加或修改日报信息统一操作
     * @param diaryInfo 日报信息
     */
    private void HandleModifyDiaryInfo (DiaryInfo diaryInfo) {
        // 获取进程中的用户数据
        UserIdentityDto userIdentityDto = UserIdThreadLocalUtils.getUser();
        if (diaryInfo.getId() == 0) {
            diaryInfo.setCreateUserId(userIdentityDto.getId());
            diaryInfo.setCreateTime(LocalDateTime.now());
            diaryInfo.setIsDeleted(false);
        }
        diaryInfo.setUpdateUserId(userIdentityDto.getId());
        diaryInfo.setUpdateTime(LocalDateTime.now());
    }

    /**
     * 根据id修改一则日报信息记录
     * @param addDiaryInfoVo 需要修改的日志信息
     */
    @Override
    public ResponseResult<Boolean> UpdateDiaryInfoById(AddDiaryInfoVo addDiaryInfoVo) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (addDiaryInfoVo == null || addDiaryInfoVo.getId() <= 0) {
            // 缺少参数 日报id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        DiaryInfo diaryInfo = diaryInfoMapper.selectById(addDiaryInfoVo.getId());
        // 代码拷贝
        BeanUtils.copyProperties(addDiaryInfoVo, diaryInfo);
        this.HandleModifyDiaryInfo(diaryInfo);
        Boolean flag = diaryInfoMapper.updateById(diaryInfo) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 根据id删除一则日报信息记录
     * @param id 日报信息id
     */
    @Override
    public ResponseResult<Boolean> DeleteDiaryInfoById(int id) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        // 参数审查
        if (id <= 0) {
            // 缺少参数 日报id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        DiaryInfo diaryInfo = diaryInfoMapper.selectById(id);
        diaryInfo.setIsDeleted(true);
        this.HandleModifyDiaryInfo(diaryInfo);
        Boolean flag = diaryInfoMapper.updateById(diaryInfo) > 0;
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), flag, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 根据条件（创建时间）分页查询日报信息
     * @param searchDiaryInfoVo 查询条件
     */
    @Override
    public ResponseResult<PageResponseDto<List<DiaryInfoDto>>> SelectDiaryInfoListByConditions(SearchDiaryInfoVo searchDiaryInfoVo) {
        ResponseResult<PageResponseDto<List<DiaryInfoDto>>> result = new ResponseResult<>();
        // 参数审查
        if (searchDiaryInfoVo == null) {
            // 缺少参数 日报所属人id
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        // 分页响应对象
        PageResponseDto<List<DiaryInfoDto>> pageResponseDto = new PageResponseDto<>();
        LambdaQueryWrapper<DiaryInfo> diaryQuery = new LambdaQueryWrapper<>();
        diaryQuery.eq(DiaryInfo::getIsDeleted, false);
        // 当天时间范围
        LocalDate currentDate = searchDiaryInfoVo.getCreateTime().toLocalDate();
        LocalDateTime currentDateStartTime = currentDate.atTime(0, 0, 0);
        LocalDateTime currentDateEndTime = currentDate.atTime(23, 59, 59);
        // 当天时间范围查询
        diaryQuery.between(DiaryInfo::getCreateTime, currentDateStartTime, currentDateEndTime);
        // 创建时间倒序排
        diaryQuery.orderByDesc(DiaryInfo::getCreateTime);
        // 分页条件
        IPage<DiaryInfo> diaryPage = new Page<>(searchDiaryInfoVo.getPageIndex(), searchDiaryInfoVo.getPageSize());
        // 分页查询结果
        IPage<DiaryInfo> diaryInfoIPage = diaryInfoMapper.selectPage(diaryPage, diaryQuery);
        // 设置总数据个数
        pageResponseDto.setSize(diaryInfoMapper.selectCount(diaryQuery).intValue());
        // 分页查询日志原始记录
        List<DiaryInfo> diaryRecords = diaryInfoIPage.getRecords();
        // 分页查询日志处理后的数据
        List<DiaryInfoDto> diaryInfoDtos = new ArrayList<>();
        // 单日志暂存对象
        DiaryInfoDto diaryInfoDto = null;
        // 日志原始记录处理流程
        for (DiaryInfo diaryRecord : diaryRecords) {
            diaryInfoDto = new DiaryInfoDto();
            BeanUtils.copyProperties(diaryRecord, diaryInfoDto);
            diaryInfoDtos.add(diaryInfoDto);
        }
        // 分页响应对象设置日志处理后数据
        pageResponseDto.setData(diaryInfoDtos);
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), pageResponseDto, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    @Autowired
    private ProjectInfoService projectInfoService;

    /**
     * 获取本月的不同项目的日报详情列表
     */
    @Override
    public ResponseResult<List<DiaryContentByMonthDto>> GetDiaryListByMonth(SearchDiaryInfoVo searchDiaryInfoVo) {
        ResponseResult<List<DiaryContentByMonthDto>> result = new ResponseResult<>();
        // 参数审查
        if (searchDiaryInfoVo == null) {
            // 缺少参数
            result.error(AppHttpCodeEnum.PARAM_REQUIRE.getCode(), AppHttpCodeEnum.PARAM_REQUIRE.getErrorMessage());
            return result;
        }
        LambdaQueryWrapper<DiaryInfo> diaryQuery = new LambdaQueryWrapper<>();
        LocalDateTime createTime = searchDiaryInfoVo.getCreateTime();
        String year = createTime.getYear() + "";
        int month = createTime.getMonth().getValue();
        String monthStr = "";
        if (month < 10) {
            monthStr = "0" + month;
        } else {
            monthStr = "" + month;
        }
        diaryQuery.eq(DiaryInfo::getIsDeleted, false)
                .like(DiaryInfo::getCreateTime, year + "-" + monthStr + "%");
        List<DiaryInfo> diaryInfoList = diaryInfoMapper.selectList(diaryQuery);
        Map<Integer, List<DiaryInfo>> diaryInfoMap = diaryInfoList.stream().collect(Collectors.groupingBy(DiaryInfo::getProjectId));
        Set<Integer> projectIdList = diaryInfoMap.keySet();
        List<DiaryContentByMonthDto> diaryContentByMonthDtoList = new ArrayList<>();
        DiaryContentByMonthDto diaryContentByMonthDto = null;
        for (Integer projectId : projectIdList) {
            diaryContentByMonthDto = new DiaryContentByMonthDto();
            String projectName = projectInfoService.GetProjectNameById(projectId);
            diaryContentByMonthDto.setProjectName(projectName);
            List<DiaryInfo> diaryByProIdList = diaryInfoMap.get(projectId);
            List<String> diaryContentList = new ArrayList<>();
            for (DiaryInfo diaryInfo : diaryByProIdList) {
                diaryContentList.add(diaryInfo.getWorkDetail());
            }
            diaryContentByMonthDto.setContent(diaryContentList);
            diaryContentByMonthDtoList.add(diaryContentByMonthDto);
        }
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), diaryContentByMonthDtoList, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /**
     * 获取每天的日报数
     */
    @Override
    public ResponseResult<List<DiaryCountGroupByDayDto>> GetCurrentDayDiaryCount() {
        ResponseResult<List<DiaryCountGroupByDayDto>> result = new ResponseResult<>();
        LambdaQueryWrapper<DiaryInfo> diaryQuery = new LambdaQueryWrapper<>();
        diaryQuery.eq(DiaryInfo::getIsDeleted, false);
        List<DiaryInfo> diaryInfoList = diaryInfoMapper.selectList(diaryQuery);
        Set<LocalDate> currentDaySet = new HashSet<>();
        for (DiaryInfo diaryInfo : diaryInfoList) {
            currentDaySet.add(diaryInfo.getCreateTime().toLocalDate());
        }
        List<DiaryCountGroupByDayDto> groupByDayDtoList = new ArrayList<>();
        DiaryCountGroupByDayDto diaryCountGroupByDayDto = null;
        for (LocalDate currentDay : currentDaySet) {
            diaryCountGroupByDayDto = new DiaryCountGroupByDayDto();
            diaryCountGroupByDayDto.setCurrentDay(currentDay);
            LocalDateTime currentDateStartTime = currentDay.atTime(0, 0, 0);
            LocalDateTime currentDateEndTime = currentDay.atTime(23, 59, 59);
            // 当天时间范围查询
            diaryQuery = new LambdaQueryWrapper<>();
            diaryQuery.between(DiaryInfo::getCreateTime, currentDateStartTime, currentDateEndTime);
            diaryQuery.eq(DiaryInfo::getIsDeleted, false);
            Integer diaryCount = diaryInfoMapper.selectCount(diaryQuery).intValue();
            diaryCountGroupByDayDto.setDiaryCount(diaryCount);
            groupByDayDtoList.add(diaryCountGroupByDayDto);
        }
        result.ok(AppHttpCodeEnum.SUCCESS.getCode(), groupByDayDtoList, AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

}
